package com.gopay.checkorder.service.task;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.dao.BisBankOrderQueryDAO;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.alarm.OrderAlarmDataCollector;
import com.gopay.checkorder.service.alarm.OrderAlarmRecordStorage;
import com.gopay.checkorder.service.task.thread.CheckOrderThread;
import com.gopay.common.domain.bank.BankOrder;

public class CmbCheckOrderTaskImpl implements Task{
    
    private final static Logger logger = LoggerFactory.getLogger(CmbCheckOrderTaskImpl.class);
    
    private static final int MAX_THREAD_COUNT = 10;

    private ExecutorService threadPool = Executors
            .newFixedThreadPool(MAX_THREAD_COUNT);

    @Resource(name = "bisBankOrderQueryDAO")
    private BisBankOrderQueryDAO bisBankOrderQueryDAO;

    @Resource(name = "bankOrderService")
    private BankOrderService bankOrderService;

    @Resource(name = "orderAlarmRecordStorage")
    private OrderAlarmRecordStorage orderAlarmRecordStorage;

    private String BANK = "CMB";

    /**
     * 银行流水状态
     */
    private String orderStatus;

    /**
     * 对单次数
     */
    private int totalCheckTimes;
    
    private void printLog(StopWatch sw, String bank, String orderStatus,
            int totalCheckTimes, String prefix) {
        sw.split();
        logger.error(prefix + "------,bank=" + BANK + ",orderStatus="
                + orderStatus + ",totalCheckTimes=" + totalCheckTimes + ",耗时="
                + sw.getSplitTime());
    }

    @Override
    public void doTask() {
        try{
            StopWatch sw = new StopWatch();
            sw.start();
            printLog(sw, BANK, orderStatus, totalCheckTimes,"CmbCheckOrderTaskImpl------start");

            int pageSize = 300;
            int pageIndex = 1;

            List<BankOrder> list = getCheckOrder(orderStatus, totalCheckTimes,
                    pageIndex, pageSize);
            printLog(sw, BANK, orderStatus, totalCheckTimes,"CmbCheckOrderTaskImpl------list.size()=" + list.size()+ ",pageIndex=" + pageIndex);
            // 订单对账报警采集者
            OrderAlarmDataCollector alarmCollector = new OrderAlarmDataCollector();

            // 订单队列
            ConcurrentLinkedQueue<BankOrder> queue = new ConcurrentLinkedQueue<BankOrder>();
            queue.addAll(list);

            // 同步锁存器
            CountDownLatch latch = new CountDownLatch(queue.size());

            // 线程池中线程全部参与
            for (int i = 0; i < MAX_THREAD_COUNT; i++) {
                CheckOrderThread thread = new CheckOrderThread(bankOrderService, queue, latch, alarmCollector);
                threadPool.execute(thread);

            }

            // 同步锁存器等待所有线程执行完成
            if (!latch.await(118, TimeUnit.SECONDS)) {
                logger.error("同步锁存器等待超时了 latch.count=" + latch.getCount());
                threadPool.awaitTermination(1, TimeUnit.SECONDS);
            }
            // 判断报警阈值并保存报警记录
            orderAlarmRecordStorage.store(alarmCollector);

            printLog(sw, BANK, orderStatus, totalCheckTimes,
                    "CmbCheckOrderTaskImpl------end");
            sw.stop();
        }catch (Throwable t) {
            logger.error("执行对单Task时出现异常", t);
        }
        
    }
    /**
     * 分页查询对账记录
     * 
     * @param orderStatus
     * @param totalCheckTimes
     * @param pageIndex
     * @param pageSize
     * @return
     */
    protected List<BankOrder> getCheckOrder(String orderStatus,
            int totalCheckTimes, int pageIndex, int pageSize) {

            return bisBankOrderQueryDAO.getCheckOrderByBankExcludeB2b(orderStatus,
                    totalCheckTimes, pageIndex, pageSize, BANK);

    }

    public String getOrderStatus() {
        return orderStatus;
    }

    public void setOrderStatus(String orderStatus) {
        this.orderStatus = orderStatus;
    }

    public int getTotalCheckTimes() {
        return totalCheckTimes;
    }

    public void setTotalCheckTimes(int totalCheckTimes) {
        this.totalCheckTimes = totalCheckTimes;
    }

}
